package com.polarrose.wsf.accesscontrol;

import static com.polarrose.wsf.accesscontrol.IpFilteringAccessManager.AccessPolicy.Accept;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;

import com.polarrose.wsf.accesscontrol.IpUtils.IpAndMask;

public class IpFilteringAccessManager implements AccessManager {

	public enum AccessPolicy {
		Accept, Deny
	}

	public static final String DEFAULT_HEADER_TO_CHECK = "X-Forwarded-For";
	public static final String REMOTE_ADDR_HEADER = "Remote-Addr";
	private IpAndMask[] allowedIpAndMasks;
	private AccessPolicy policy = Accept;
	private String headerToCheck = DEFAULT_HEADER_TO_CHECK;

	public boolean accessGranted(HttpServletRequest request) {
		if (allowedIpAndMasks == null) {
			return policy == Accept;
		}

		String header = null;
		if (headerToCheck.equals(REMOTE_ADDR_HEADER)) {
			header = request.getRemoteAddr();
		} else {
			header = request.getHeader(headerToCheck);
			if (StringUtils.isEmpty(header)) {
				return policy == Accept;
			}
		}
		IpAndMask remoteIp = IpUtils.parseIP(header);

		return IpUtils.addressMatches(remoteIp.getIp(), allowedIpAndMasks);
	}

	public void setHeaderToCheck(String headerToCheck) {
		this.headerToCheck = headerToCheck;
	}

	public void setPolicy(AccessPolicy policy) {
		this.policy = policy;
	}

	public void setAllowedHosts(String hosts) throws UnknownHostException {
		if (hosts == null) {
			return;
		}
		String[] entries = hosts.split(",");
		List<IpAndMask> allowedIpAndMasks = new ArrayList<IpAndMask>();
		for (String entry : entries) {
			entry = StringUtils.trimToNull(entry);
			if (entry == null) {
				continue;
			}
			if (IpUtils.isIP(entry)) {
				allowedIpAndMasks.add(IpUtils.parseIP(entry));
			} else {
				allowedIpAndMasks.add(IpUtils.createIpFromInetAddress(entry));
			}
		}
		this.allowedIpAndMasks = allowedIpAndMasks.toArray(new IpAndMask[allowedIpAndMasks.size()]);
	}
}
